#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <string.h> // for memcpy only
#include <util/delay.h>
#include <avr/io.h>
#include "card.h"
#include "common.h"
#include "delay_util.h"
#include "ccid.h"

#include "main.h"
#include "uart_soft.h"  // DEBUG

Card_t Card;
MetroInfo_t Metro;

#define VERBOSE_TYPE
//#define VERBOSE_ATR


void Card_t::DetermineType(void) {
    // Get ATQA and SAK from target data
    uint8_t ATQA1 = Data[0], ATQA2 = Data[1], SAK = Data[2];
    if      ((ATQA1 == 0x00) and (ATQA2 == 0x04) and (SAK == 0x09)) Type = ctMifareMini;
    else if ((ATQA1 == 0x00) and (ATQA2 == 0x04) and (SAK == 0x08)) Type = ctMifareClassic1K;
    else if ((ATQA1 == 0x00) and (ATQA2 == 0x02) and (SAK == 0x18)) Type = ctMifareClassic4K;
    else if ((ATQA1 == 0x00) and (ATQA2 == 0x44) and (SAK == 0x00)) Type = ctMifareUltralight;
    else if ((ATQA1 == 0x03) and (ATQA2 == 0x44) and (SAK == 0x20)) Type = ctMifareDESFire;
    else if ((ATQA1 == 0x00) and (ATQA2 == 0x04) and (SAK == 0x88)) Type = ctInfineonMifareClassic1K;

    else if (
            ((ATQA1 == 0x03) and (ATQA2 == 0x04) and (SAK == 0x28)) or
            ((ATQA1 == 0x00) and (ATQA2 == 0x48) and (SAK == 0x20)) or
            ((ATQA1 == 0x00) and (ATQA2 == 0x04) and (SAK == 0x28))
            )
            Type = ctJCOP;

#ifdef VERBOSE_TYPE
    switch (Type) {
        case ctUndefined:        klPrintf("Undefined\r"); break;
        case ctMifareMini:       klPrintf("MifareMini\r"); break;
        case ctMifareClassic1K:  klPrintf("MifareClassic1K\r"); break;
        case ctMifareClassic4K:  klPrintf("MifareClassic4K\r"); break;
        case ctMifareUltralight: klPrintf("MifareUltralight\r"); break;
        case ctMifareDESFire:    klPrintf("MifareDESFire\r"); break;
        case ctInfineonMifareClassic1K: klPrintf("InfineonMifareClassic1K\r"); break;
        case ctJCOP:             klPrintf("JCOP\r"); break;
    }
#endif
}


/*
 * PC/SC 3.1.3.2.3 (pcsc3_v2.01.09.pdf):
 * For contactless ICCs, the IFD subsystem must construct an ATR from the fixed elements that identify the cards.
 * ATS for JCOP and other 14443-4-compatible: file 14443-4.pdf, page 6
 */
void Card_t::ConstructATR(void) {
    // Construct ATR depending on card type
    uint8_t SAK = Data[2];
    IsMifare = !(SAK & 0x20);
    if (IsMifare) {  // MIFARE protocol
        uint8_t ATQA1 = Data[0], ATQA2 = Data[1];
        AtrLength = 20;
        ATR[0] = 0x3B;  // Initial
        ATR[1] = 0x8F;  // T0: Higher nibble 8 means no TA1, TB1, TC1 only TD1 is following. Lower nibble is the number of historical bytes
        ATR[2] = 0x80;  // TD1: Higher nibble 8 means no TA2, TB2, TC2 only TD2 is following. Lower nibble 0 means T = 0
        ATR[3] = 0x01;  // TD2: Higher nibble 0 means no TA3, TB3, TC3, TD3 following. Lower nibble 1 means T = 1
        // Historical bytes
        ATR[4] = 0x80;  // T1: Category indicator byte, 80 means A status indicator may be present in an optional COMPACT-TLV data object
        ATR[5] = 0x4F;  // Application identifier Presence indicator
        ATR[6] = 0x0C;  // Length
        // 5 bytes: Registered application provider identifier (RID); pcsc3_v2.01.08_sup.pdf
        // The PC/SC Workgroup has its own 5-byte RID. The specification mandates to use this RID for compliant IFD subsystems.
        ATR[7] = 0xA0;
        ATR[8] = 0x00;
        ATR[9] = 0x00;
        ATR[10] = 0x03;
        ATR[11] = 0x06;
        // *** PIX (7 bytes max) ***
        ATR[12] = 0x03; // SS: Byte for standard; here ISO 14443 A, part 3
        // The two bytes for Card Name represent a number which will be assigned by the PC/SC Workgroup upon request
        ATR[13] = 0x00; ATR[14] = 0x00;     // No information given
        if      ((ATQA1 == 0x00) and (ATQA2 == 0x04) and (SAK == 0x09)) { ATR[13] = 0x00; ATR[14] = 0x26; } // MifareMini
        else if ((ATQA1 == 0x00) and (ATQA2 == 0x04) and (SAK == 0x08)) { ATR[13] = 0x00; ATR[14] = 0x01; } // MifareClassic1K
        else if ((ATQA1 == 0x00) and (ATQA2 == 0x02) and (SAK == 0x18)) { ATR[13] = 0x00; ATR[14] = 0x02; } // MifareClassic4K
        else if ((ATQA1 == 0x00) and (ATQA2 == 0x44) and (SAK == 0x00)) { ATR[13] = 0x00; ATR[14] = 0x03; } // MifareUltralight
        // RFU: shall be set to zero
        ATR[15] = 0x00;
        ATR[16] = 0x00;
        ATR[17] = 0x00;
        ATR[18] = 0x00;
    }
    else {   // 14443-4 protocol (T=CL)
        //klPrintf("SensRes: %X %X; SelRes: %X\r", Data[0], Data[1], Data[2]);
        uint8_t NFCIDLength = Data[3];
        uint8_t ATSLength = 0;
        //klPrintf("NFCIDLength: %X\r", NFCIDLength);
        //klPrintf("NFCID: %A\r", &Data[4], NFCIDLength);
        uint8_t *ATS = &Data[4+NFCIDLength];    // TL
        ATSLength = *ATS++;                     // Get length and move to first byte of ATS (T0)
        //klPrintf("ATSLength: %X\r", ATSLength);
        uint8_t HistoricalBytesLength = 0, *HistoricalBytes = ATS+1;    // Next byte after T0 (TA1 or TB1 or TC1 or HistoricalByte)
        if (ATSLength > 1) {    // There are something else besides mandatory TL byte
            //klPrintf("ATS: %A\r", ATS, ATSLength-1);
            uint8_t T0 = ATS[0];
            // The least significant half byte b4 to b1 is called FSCI and codes FSC. The FSC defines the maximum size of a frame accepted by the PICC.
            HistoricalBytesLength = ATSLength - 1 - 1;  // -Length -T0
            if (T0 & 0x10) {    // TA1 exist
                HistoricalBytesLength--;
                HistoricalBytes++;
            }
            if (T0 & 0x20) {    // TB1 exist
                HistoricalBytesLength--;
                HistoricalBytes++;
            }
            if (T0 & 0x40) {    // TC1 exist
                HistoricalBytesLength--;
                HistoricalBytes++;
            }
            //klPrintf("HistoricalBytesLength: %u; HistoricalBytes: %A\r", HistoricalBytesLength, HistoricalBytes, HistoricalBytesLength);
        }

        ATR[0] = 0x3B;  // Initial
        ATR[1] = 0x80 | HistoricalBytesLength; // T0: Higher nibble 8 means no TA1, TB1, TC1 only TD1 is following. Lower nibble is the number of historical bytes
        ATR[2] = 0x80;  // TD1: Higher nibble 8 means no TA2, TB2, TC2 only TD2 is following. Lower nibble 0 means T = 0
        ATR[3] = 0x01;  // TD2: Higher nibble 0 means no TA3, TB3, TC3, TD3 following. Lower nibble 1 means T = 1
        // Historical bytes from ATS response
        if (HistoricalBytesLength > 0) {
            memcpy(&ATR[4], HistoricalBytes, HistoricalBytesLength);
            AtrLength = 4 + HistoricalBytesLength + 1;  // 4 mandatory bytes + historical bytes + TCK
        }
        else AtrLength = 5;
    }
    // TCK
    uint8_t TCK=0;
    for (uint8_t i=1; i<AtrLength-1; i++) TCK ^= ATR[i];    // Exclusive-OR of bytes T0 to Tk
    ATR[AtrLength-1] = TCK;

#ifdef VERBOSE_ATR
    klPrintf("ATR: %A\r", ATR, AtrLength);
#endif
}

void Card_t::MetroInfoDescrypted(uint8_t *MemBuf) {
    if (MemBuf[0] != 0x04) { return; }

    Metro.AppID = MemBuf[16];
    Metro.AppID <<= 8;
    Metro.AppID |= MemBuf[17];
    Metro.AppID >>= 6;
    Metro.PAppID = &Metro.AppID;


    Metro.Cardtype = MemBuf[17];
    Metro.Cardtype <<= 8;
    Metro.Cardtype |= MemBuf[18];
    Metro.Cardtype >>= 4;
    Metro.Cardtype &= 0x03FF;
    Metro.PCardType = &Metro.Cardtype;


    Metro.TcktNmb = MemBuf[18];
    Metro.TcktNmb <<= 8;
    Metro.TcktNmb |= MemBuf[19];
    Metro.TcktNmb <<= 8;
    Metro.TcktNmb |= MemBuf[20];
    Metro.TcktNmb <<= 8;
    Metro.TcktNmb |= MemBuf[21];
    Metro.TcktNmb <<= 4;
    Metro.TcktNmb |= (MemBuf[22] >> 4);
    Metro.PTcktNmb = &Metro.TcktNmb;

    Metro.Layout = MemBuf[22];
    Metro.Layout &= 0x0F;
    Metro.PLayout = &Metro.Layout;

    Metro.BlankbestBefore = MemBuf[23];
    Metro.BlankbestBefore <<= 8;
    Metro.BlankbestBefore |= MemBuf[24];
    Metro.PBlankBestBefore = &Metro.BlankbestBefore;

    Metro.Issued = MemBuf[32];
    Metro.Issued <<= 8;
    Metro.Issued |= MemBuf[33];
    Metro.PIssued = &Metro.Issued;

    Metro.BestInDays = MemBuf[34];
    Metro.PBestInDays = &Metro.BestInDays;

    Metro.PassesLeft = MemBuf[36];
    Metro.PassesLeft <<= 8;
    Metro.PassesLeft |= MemBuf[37];
    Metro.PPassesLeft = &Metro.PassesLeft;


    Metro.StationLastEnter = MemBuf[38];
    Metro.StationLastEnter <<= 8;
    Metro.StationLastEnter |= MemBuf[39];
    Metro.PStationLastEnter = &Metro.StationLastEnter;

    Metro.HASH = MemBuf[40];
    Metro.HASH <<= 8;
    Metro.HASH |= MemBuf[41];
    Metro.HASH <<= 8;
    Metro.HASH |= MemBuf[42];
    Metro.HASH <<= 8;
    Metro.HASH |= MemBuf[43];
    Metro.PHASH = &Metro.HASH;

    klPrintf("ID: %U\r", *Metro.PTcktNmb);
    klPrintf("Layout: %u\r", *Metro.PLayout);
    klPrintf("AppID: %u\r", *Metro.PAppID);
    klPrintf("CardType: %u\r", *Metro.PCardType);
    klPrintf("Issued: %u\r", *Metro.PIssued);
    klPrintf("BlankBestBefore: %u\r", *Metro.PBlankBestBefore);
    klPrintf("BestInDays: %u\r", *Metro.PBestInDays);
    klPrintf("Passes left: %u\r", *Metro.PPassesLeft);
    klPrintf("Station last enter: %u\r", *Metro.PStationLastEnter);
    klPrintf("HASH: %U\r", *Metro.PHASH);

}
